package com.briup;

import com.briup.client.Client;
import com.briup.client.Gather;
import com.briup.server.DBStore;
import com.briup.server.Server;
import com.briup.support.ConfigurationAware;
import com.briup.support.PropertiesAware;
import com.briup.util.Backup;
import com.briup.util.Log;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 先读取 配置文件 解析xml 使用Dom4j
 */
public class ConfigurationImpl implements Configuration {
    private static Map<String,Object> map=new HashMap<>();


    //静态代码块 跟随类加载 很早 且只加载一次
    static {
        ConfigurationImpl configuration = new ConfigurationImpl();
        //获取解析器
        SAXReader reader = SAXReader.createDefault();
        try {
            //加载文件并解析
            Document doc = reader.read("src/main/resources/config.xml");
            //获取文档的根节点 config节点
            Element conf = doc.getRootElement();
            List<Element> elements = conf.elements();
            //遍历根元素的一级子节点
            for (Element element : elements) {
                //获取一级标签的属性节点
                Attribute classAtt = element.attribute("class");
                //获取属性的值   全限定类名
                String className = classAtt.getValue();
                //通过反射  加载类
                Class<?> aClass = Class.forName(className);
                //通过反射创建对象 调用默认无参构造
                Object o =  aClass.newInstance();
                //获取一级标签的名字
                String name = element.getName();
                //存入一级标签名 和对应的对象
                map.put(name,o);
                //获取一级标签的子标签
                List<Element> params = element.elements();
                //创建map  收集对应的参数
                Properties p = new Properties();
                //遍历2级标签
                for (Element param : params) {
                    String paramName = param.getName();
                    String paramValue = param.getTextTrim();
                    System.out.println(paramName+paramValue);
                    p.setProperty(paramName,paramValue);
                }
                if (o instanceof  PropertiesAware){
                    PropertiesAware pa= (PropertiesAware) o;
                    pa.init(p);
                }


            }


        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            map.forEach((k,o)->{
                if (o instanceof ConfigurationAware){
                    ConfigurationAware ca= (ConfigurationAware) o;
                    try {
                        ca.setConfiguration(configuration);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

    }

    @Override
    public Log getLogger() throws Exception {
        return (Log) map.get("Log");
    }

    @Override
    public Server getServer() throws Exception {
        return (Server) map.get("Server");
    }

    @Override
    public Client getClient() throws Exception {
        return (Client) map.get("Client");
    }

    @Override
    public DBStore getDbStore() throws Exception {
        return (DBStore) map.get("DBStore");
    }

    @Override
    public Gather getGather() throws Exception {
        return (Gather) map.get("Gather");
    }

    @Override
    public Backup getBackup() throws Exception {
        return (Backup) map.get("BackUp");
    }
}
